const WpsCom = require("./wps_com");
// debugger
const CommonAxerrHG = require("../../tool/CommonAxerrHandlerGenerator").CommonAxerrHandlerGen;
const util = require("util");
const FormData = require("form-data");
const rs = require("randomstring");
const path = require("path");
const SpecialGroupApplication = require("./SpecialGroupApplication").SpeciaGroupApplication


class ModelListItemsInFolder {
  /**
   * 
   * @param {Number} id 
   * @param {Number} ctime Date.now()/1000
   * @param {Number} mtime  Date.now()/1000
   * @param {String} fname 
   * @param {Number} fsize 
   * @param {"folder"|"file"} ftype 
   * @param {Number} fver 
   */
  constructor(id, ctime, mtime, fname, fsize, ftype, fver) {
    this.id = id;
    this.fname = fname;
    this.fsize = fsize;
    this.ftype = ftype;
    this.fver = fver;
    this.create_time = new Date(ctime * 1000);
    this.modified_time = new Date(mtime * 1000)
  }

  get is_file() {
    return this.ftype == "file"
  }

  get is_folder() {
    return this.ftype == "folder"
  }
}





class SpecialGroup {
  /**
   * 
   * @param {WpsCom} wpscom 
   * @param {Number} id 
   * @param {String} name 
   */
  constructor(wpscom, id, name) {
    this.kdocs = wpscom;
    this.name = name;
    this.id = id;

    this.app = new SpecialGroupApplication(this);
  }

  get axios() {
    return this.kdocs.axios;
  }

  /**
   * @returns {Promise<{
   * ok:Boolean,
   * msg:String,
   * data:{
   * histories:Array<{
   * fileid:Number,
   * fileidstr:String,
   * fname:String,
   * ftype:String,
   * fver:Number,
   * groupid:Number,
   * id:Number
   * }>
   * }
   * }>}
   * @param {Number} file_id 
   * @param {Number} offset
   * @param {Number} count
   */
  getFileHistory(file_id, offset = 0, count = 20) {
    return new Promise(resolve => {
      this.axios.get(`https://${this.kdocs.iphost}/api/v3/files/${
        file_id
        }/histories?offset=${offset}&count=${count}&groupid=${this.id}`, {
        headers: {
          host:"drive.wps.com",
          cookie: this.kdocs.cookies_as_header,
          referer: `https://drive.wps.com/group/${this.id}?zeus=1`
        }
      }).then(axresp => {
        if (axresp.data
          && util.isArray(axresp.data.histories)) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              histories: axresp.data.histories.map(e => {
                return {
                  fileid: e.fileid,
                  fileidstr: e.fileidstr,
                  fname: e.fname,
                  ftype: e.ftype,
                  fver: e.fver,
                  groupid: e.groupid,
                  id: e.id
                }
              })
            }
          })
        }
        throw axresp.data
        debugger
      }).catch(axerr => {
        CommonAxerrHG(resolve)(axerr)
      })
    })
  }


  /**
   * @returns {Promise<{ok:Boolean,msg:String,data:{
   * link:String
   * }}>}
   * @param {Number} file_id 
   * @param {Number} history_id 必须是旧版本的history的id，不能是最新版本的！
   */
  getFileHistoryDownloadLinkByHistoryId(file_id, history_id) {

    return new Promise(async resolve => {
      if (history_id == 0) {
        //说明是最新版本 调用另一个api
        let o_newestVersionLink = await this.getFileNewestVersionDownloadLink(file_id);
        return resolve(o_newestVersionLink);
      }
      this.axios.get(`https://${this.kdocs.iphost}/api/v3/files/${
        file_id}/histories/${history_id}/download?groupid=${this.id}`, {
        headers: {
          host:"drive.wps.com",
          cookie: this.kdocs.cookies_as_header,
          referer: `https://drive.wps.com/group/${this.id}?zeus=1`
        }
      }).then(axresp => {
        // debugger
        if (axresp.data
          && axresp.data.fileinfo
          && axresp.data.fileinfo.url) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              link: axresp.data.fileinfo.url
            }
          })
        }
        throw axresp.data
      }).catch(axerr => {
        CommonAxerrHG(resolve)(axerr)
      })
    })
  }

  /**
   * @returns {Promise<{ok:Boolean,msg:String,data:{
   * link:String
   * }}>}
   * @param {String} file_id 
   */
  getFileNewestVersionDownloadLink(file_id) {
    return new Promise(resolve => {
      this.axios.get(`https://${this.kdocs.iphost}/api/v3/groups/${
        this.id}/files/${
        file_id}/download`, {
        headers: {
          host:"drive.wps.com",
          cookie: this.kdocs.cookies_as_header,
          referer: `https://drive.wps.com/group/${this.id}?zeus=1`
        }
      }).then(axresp => {
        // debugger
        if (axresp.data
          && axresp.data.fileinfo
          && axresp.data.fileinfo.url) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              link: axresp.data.fileinfo.url
            }
          })
        }
        throw axresp.data
      }).catch(axerr => {
        CommonAxerrHG(resolve)(axerr)
      })
    })
  }

  /**
   * @returns {Promise<{ok:Boolean,msg:String,data:{
   * AccessKeyId:String,
   * key:String,
   * policy:String,
   * signature:String,
   * upload_domain:String
   * }}>}
   * @param {String} filename 
   * @param {Number} parent_id 
   * @param {Number} size_declared 
   */
  requestUploadToken(filename, parent_id = 0, size_declared = 1) {
    return new Promise(resolve => {
      this.axios.get(`https://${this.kdocs.iphost}/api/files/upload/request`, {
        params: {
          groupid: this.id,
          parentid: parent_id,
          size: size_declared,
          name: filename,
          contenttype: 'application/x-msdownload' || 'application/pdf',
          successactionstatus: 201,
          store: 's3_obs_oss',
        },
        headers: {
          host:"drive.wps.com",
          cookie: this.kdocs.cookies_as_header,
          referer: `https://drive.wps.com/group/${this.id}?zeus=1`
        }
      }).then(axresp => {
        // debugger
        if (axresp.data
          && axresp.data.result == "ok"
          && axresp.data.url
          && axresp.data.store == "obs"
          && axresp.data.signature
          && axresp.data.policy
          && axresp.data.key
          && axresp.data.AccessKeyId) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              AccessKeyId: axresp.data.AccessKeyId,
              key: axresp.data.key,
              policy: axresp.data.policy,
              signature: axresp.data.signature,
              upload_domain: axresp.data.url
            }
          })
        }
        throw axresp.data
      }).catch(axerr => {
        CommonAxerrHG(resolve)(axerr);
      })
    })
  }

  /**
   * @returns {Promise<{ok:Boolean,msg:String,data:{
   * fileidstr:String,
   * id:Number,
   * fname:String,
   * fsize:Number,
   * fver:Number,
   * groupid:Number
   * }}>}
   * @param {String} name 非常重要，关系到是否会变成文件的新版本
   * @param {String} object_key 
   * @param {String} sha1 来自上传Huawei对象存储得到的Etag
   * @param {Number} size_declared 
   * @param {Number} parent_id 
   */
  createFile_afterUploadObs_100limit(name, object_key, sha1, size_declared = 1, parent_id = 0) {
    return new Promise(resolve => {
      this.axios.post(`https://${this.kdocs.iphost}/api/v3/groups/${this.id}/files`, {
        groupid: String(this.id),
        name: name,
        object_key: object_key,
        parent_path: [],
        parentid: parent_id,
        sha1: sha1,
        size: size_declared,
        store: "obs",
      }, {
        headers: {
          host:"drive.wps.com",
          cookie: this.kdocs.cookies_as_header,
          Referer: "https://drive.wps.com/"//非常重要，缺了这个的话API就会返回错误，说我没有CSRF
        },
        validateStatus: s => s == 200
      }).then(axresp => {
        // debugger
        if (axresp.data
          && axresp.data.fileidstr
          && axresp.data.id
          && axresp.data.fsize
          && axresp.data.groupid
          && axresp.data.fsize) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              fileidstr: axresp.data.fileidstr,
              fname: axresp.data.fname,
              fsize: axresp.data.fsize,
              fver: axresp.data.fver,
              groupid: axresp.data.groupid,
              id: axresp.data.id
            }
          })
        }
        throw axresp.data
      }).catch(axerr => {
        CommonAxerrHG(resolve)(axerr)
      })
    })
  }

  /**
   * @description 由于BUG,后缀名可以很长
   * @returns {Promise<{ok:Boolean,
   * msg:"CONFLICT"|String,
   * data:{
    * fileidstr:String,
    * id:Number,
    * fname:String,
    * groupid:Number
    * }}>}
   * @param {String} name 
   * @param {Number} parent_id 
   */
  createFolder_unlimitedLength(name, parent_id = 0) {
    // if (name.length > 100) {
    //   name = name.substr(0, 95);
    //   name+=rs.generate(5);
    // }
    if (name.length == 0) {
      name = "Un-Named";
    }
    let parsed = path.parse(name);
    if (parsed.name.length == 0 || parsed.name.startsWith(".")) {
      name = "Un-Named" + name
    }
    parsed = path.parse(name);
    if (parsed.name.length > 100) {
      let defined_name = name;
      let part1 = defined_name.substr(0, 100);
      let part2 = defined_name.substr(100);
      part2 = part2.split(".").join("_");
      name = `${part1}.${part2}`;
    }
    return new Promise(async resolve => {
      this.axios.post(`https://${this.kdocs.iphost}/api/v3/groups/${this.id}/files`, {
        groupid: this.id,
        name: name,
        parentid: parent_id
      }, {
        headers: {
          host:"drive.wps.com",
          cookie: this.kdocs.cookies_as_header
        },
        validateStatus: s => s = 200 || s == 403
      }).then(axresp => {
        if (axresp.status == 403
          && axresp.data.result.toLowerCase().includes("conflict")) {
          return resolve({
            ok: false,
            msg: "CONFLICT"
          })
        }
        if (axresp.status == 200
          && axresp.data
          && axresp.data.fileidstr
          && axresp.data.fname) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              fileidstr: axresp.data.fileidstr,
              id: axresp.data.id,
              fname: axresp.data.fname,
              groupid: axresp.data.groupid
            }
          })
        }
        throw { data: axresp.data, status: axresp.status };
      }).catch(axerr => {
        CommonAxerrHG(resolve)(axerr);
      })
    })
  }


  /**
   * @description 需要注意的是,所有文件夹都在offset=0的时候写入,count只针对file来限制;所以要观察有没有列到末尾,只有看最后的文件的数量是不是少于count;否则还得看下一页
   * @returns {Promise<{ok:Boolean,msg:String,data:{items:Array<ModelListItemsInFolder>}}>}
   * @param {Number} folder_id 
   * @param {Number} offset 
   * @param {Number} count 
   * @param {"fname"|"fsize"|"mtime"|"ctime"} orderby 
   * @param {"ASC"|"DESC"} order 
   */
  listItemsInFolder(folder_id = 0, offset = 0, count = 50, orderby = "mtime",
    order = "DESC") {
    let params = {
      offset: offset,
      count: count,
      filter: "all",
      orderby: orderby,
      order: order,
      parentid: folder_id
    }

    return new Promise(resolve => {
      this.axios.get(`https://${this.kdocs.iphost}/api/v3/groups/${this.id}/files`, {
        params: {
          ...params
        },
        headers: {
          host:"drive.wps.com",
          cookie: this.kdocs.cookies_as_header,
          referer: `https://drive.wps.com/group/${
            this.id}/${folder_id}?zeus=1`
        }
      }).then(axresp => {
        // debugger
        if (axresp.data
          && util.isArray(axresp.data.files)) {
          /**@type {Array<ModelListItemsInFolder>} */
          let items = [];
          items = (axresp.data.files.map(e => new ModelListItemsInFolder(
            e.id, e.ctime, e.mtime, e.fname, e.fsize, e.ftype, e.fver
          )));
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              items: items
            }
          })
        }
        throw axresp.data;
      }).catch(axerr => {
        CommonAxerrHG(resolve)(axerr)
      })
    })
  }


  /**
   * @returns {Promise<{ok:Boolean,msg:String,data:{
   * comment_id:Number}}>}
   * @param {Number} file_id 
   * @param {String} comment 
   * @param {Number} fver 
   */
  createComment_limit255(file_id, comment, fver = 1) {
    return new Promise(resolve => {
      this.axios.post(`https://${this.kdocs.iphost}/api/v3/files/${
        file_id
        }/comments`, {
        comment: comment,
        csrfmiddlewaretoken: this.kdocs.csrf_token,
        fver: fver,
        groupid: this.id
      }, {
        headers: {
          host:"drive.wps.com",
          cookie: this.kdocs.cookies_as_header
        }
      }).then(axresp => {
        // debugger
        if (axresp.data
          && axresp.data.id) {
          return resolve({
            ok: true,
            msg: "ok",
            data: {
              comment_id: axresp.data.id
            }
          })
        }
        throw axresp.data;
      }).catch(axerr => {
        // debugger
        CommonAxerrHG(resolve)(axerr);
      })
    })
  }



}




module.exports = {
  SpecialGroup: SpecialGroup
}